package com.wyw.learning.thread.lock.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 先说明一下为什么需要使用锁Lock
 *  因为Synchronized不够用
 *      1、synchronized 效率低：锁释放的情况少（执行完毕，JVM释放）、试图获取锁时不能设定超时、不能中断试图获取锁的线程
 *      2、synchronized 不够灵活（想比于synchronized而言读写锁更灵活）：加锁和释放的时机单一，每个锁仅有单一的条件（某个对象），可能是不够的
 *      3、synchronized 无法知道是否可以成功获取锁
 *
 * Lock中声明了四种方法来获取锁，分别是Lock(),tryLock(),tryLock(long time, TimeUnit unit)和lockInterruptibly()
 *  lock（）
 *      最普通的锁，如果锁在其他线程中已经被获取了，则进行等待
 *      Lock不会像synchronized一样，异常时自动释放锁
 *      所以最佳实践是在finally中释放锁，以便在异常时锁一定被释放
 *      lock()方法 不能被中断，这样就会带来很大的隐患：一旦陷入死锁，lock（）就会陷入永久的等待（重点是lock(),Lock的实现类，比如ReentrantLock是可中断锁，可以用lockInterruptbly()方法响应中断）
 *  tryLock（）
 *      用来尝试获取锁，如果当前锁没有被其他线程占用，则返回true，否返回false，代表获取锁失败
 *      这样做相比于lock功能更加强大，可以根据是否获取锁来决定后续程序的行为
 *      因为会立刻返回，即便拿不到锁也不会一直在那等，避免饥饿，可以做其他事情
 *  tryLock(long time, TimeUnit unit)
 *      超时就会放弃
 *  lockInterruptibly()
 *      相当于把tryLock(long time, TimeUnit unit)超时时间设置为无限，在等待锁的过程中，线程可以被中断
 *
 * 锁的可见性
 *  Lock的加解锁和synchronized有同样的内存语义，也就是说，下一个线程加锁后可以看到所有前一个线程解锁前发生的所有操作
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * @date 2021/7/14   9:44 下午
 * <p>
 * Update History:
 * Author        Time            Content
 */
public class MustUnlock {
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();
        try{
            //获取锁保护的资源
            System.out.println(Thread.currentThread().getName() +
                    "开始执行任务");
        } finally {
            lock.unlock();
        }
    }

}
